#include "syntaxhighlighter.h"

SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    // 关键字格式
    keywordFormat.setForeground(Qt::darkBlue);
    keywordFormat.setFontWeight(QFont::Bold);

    // 类名格式
    classFormat.setForeground(Qt::darkMagenta);
    classFormat.setFontWeight(QFont::Bold);

    // 单行注释格式
    singleLineCommentFormat.setForeground(Qt::darkGreen);

    // 多行注释格式
    multiLineCommentFormat.setForeground(Qt::darkGreen);

    // 字符串格式
    quotationFormat.setForeground(Qt::darkRed);

    // 函数格式
    functionFormat.setForeground(Qt::blue);

    // 预处理器格式
    preprocessorFormat.setForeground(Qt::darkGray);
    preprocessorFormat.setFontWeight(QFont::Bold);

    // 数字格式
    numberFormat.setForeground(Qt::darkCyan);

    // 定义C++和Java关键字
    QStringList keywordPatterns;
    keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b"
                    << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b"
                    << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b"
                    << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b"
                    << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b"
                    << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b"
                    << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b"
                    << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b"
                    << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b"
                    << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bbool\\b"
                    << "\\bfloat\\b" << "\\busing\\b" << "\\breturn\\b"
                    << "\\bif\\b" << "\\belse\\b" << "\\bfor\\b" << "\\bwhile\\b"
                    << "\\bdo\\b" << "\\bswitch\\b" << "\\bcase\\b" << "\\bbreak\\b"
                    << "\\bcontinue\\b" << "\\bgoto\\b" << "\\bdefault\\b"
                    << "\\btry\\b" << "\\bcatch\\b" << "\\bfinally\\b" << "\\bthrow\\b" << "\\bthrows\\b" << "\\bnew\\b"
                    << "\\bdelete\\b" << "\\bthis\\b" << "\\btrue\\b" << "\\bfalse\\b"
                    << "\\bnullptr\\b" << "\\band\\b" << "\\bor\\b" << "\\bnot\\b"
                    << "\\basm\\b" << "\\bauto\\b" << "\\bdynamic_cast\\b"
                    << "\\bconst_cast\\b" << "\\bstatic_cast\\b" << "\\breinterpret_cast\\b"
                    << "\\bsizeof\\b" << "\\btypeid\\b" << "\\bexplicit\\b"
                    << "\\bexport\\b" << "\\bmutable\\b" << "\\bregister\\b"
                    << "\\btypename\\b" << "\\bwchar_t\\b"
                    // Java keywords
                    << "\\babstract\\b" << "\\bassert\\b" << "\\bbyte\\b" << "\\bextends\\b"
                    << "\\bfinal\\b" << "\\bimplements\\b" << "\\bimport\\b" << "\\binstanceof\\b"
                    << "\\binterface\\b" << "\\bnative\\b" << "\\bnull\\b" << "\\bpackage\\b"
                    << "\\bstrictfp\\b" << "\\bsuper\\b" << "\\bsynchronized\\b" << "\\btransient\\b"
                    << "\\bFalse\\b" << "\\bNone\\b" << "\\bTrue\\b"
                    << "\\band\\b" << "\\bas\\b" << "\\bassert\\b"
                    << "\\basync\\b" << "\\bawait\\b" << "\\bbreak\\b"
                    << "\\bclass\\b" << "\\bcontinue\\b" << "\\bdef\\b"
                    << "\\bdel\\b" << "\\belif\\b" << "\\belse\\b"
                    << "\\bexcept\\b" << "\\bfinally\\b" << "\\bfor\\b"
                    << "\\bfrom\\b" << "\\bglobal\\b" << "\\bif\\b"
                    << "\\bimport\\b" << "\\bin\\b" << "\\bis\\b"
                    << "\\blambda\\b" << "\\bnonlocal\\b" << "\\bnot\\b"
                    << "\\bor\\b" << "\\bpass\\b" << "\\braise\\b"
                    << "\\breturn\\b" << "\\btry\\b" << "\\bwhile\\b"
                    << "\\bwith\\b" << "\\byield\\b";


    foreach (const QString &pattern, keywordPatterns) {
        HighlightingRule rule;
        rule.pattern = QRegularExpression(pattern);
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }

    // 类名规则
    HighlightingRule classRule;
    classRule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b");
    classRule.format = classFormat;
    highlightingRules.append(classRule);

    // 函数规则
    HighlightingRule functionRule;
    functionRule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()");
    functionRule.format = functionFormat;
    highlightingRules.append(functionRule);

    // 预处理器规则
    HighlightingRule preprocessorRule;
    preprocessorRule.pattern = QRegularExpression("#.*");
    preprocessorRule.format = preprocessorFormat;
    highlightingRules.append(preprocessorRule);

    // 单行注释规则
    HighlightingRule singleLineCommentRule;
    singleLineCommentRule.pattern = QRegularExpression("//[^\n]*");
    singleLineCommentRule.format = singleLineCommentFormat;
    highlightingRules.append(singleLineCommentRule);

    // 多行注释规则
    commentStartExpression = QRegularExpression("/\\*");
    commentEndExpression = QRegularExpression("\\*/");

    // 字符串规则
    HighlightingRule quotationRule;
    quotationRule.pattern = QRegularExpression("\".*\"");
    quotationRule.format = quotationFormat;
    highlightingRules.append(quotationRule);

    // 数字规则
    HighlightingRule numberRule;
    numberRule.pattern = QRegularExpression("\\b[0-9]+\\b");
    numberRule.format = numberFormat;
    highlightingRules.append(numberRule);
}

void SyntaxHighlighter::highlightBlock(const QString &text)
{
    // 应用所有高亮规则
    for (const HighlightingRule &rule : highlightingRules) {
        QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
        while (matchIterator.hasNext()) {
            QRegularExpressionMatch match = matchIterator.next();
            setFormat(match.capturedStart(), match.capturedLength(), rule.format);
        }
    }

    // 处理多行注释
    setCurrentBlockState(0);

    int startIndex = 0;
    if (previousBlockState() != 1)
        startIndex = text.indexOf(commentStartExpression);

    while (startIndex >= 0) {
        QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
        int endIndex = match.capturedStart();
        int commentLength = 0;
        if (endIndex == -1) {
            setCurrentBlockState(1);
            commentLength = text.length() - startIndex;
        } else {
            commentLength = endIndex - startIndex + match.capturedLength();
        }
        setFormat(startIndex, commentLength, multiLineCommentFormat);
        startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
    }
}
